package core;

import fileoperation.FileCreation;
import gitobject.Commit;
import gitobject.GitObject;
import gitobject.Tree;
import repository.Repository;
import stage.Index;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class JitReset {
    /**
     * Reset current HEAD to the specified state with specified mode.
     * @param mode
     * @param commitId
     * @throws Exception
     */
    public static void resetMode(String mode, String commitId) throws Exception {
        if (commitId.length() > 6) commitId = commitId.substring(0,6);
        String id = commitExists(commitId);
        if ("".equals(id)) {
            System.out.println("fatal: ambiguous argument '" + commitId + "': unknown revision or path not in the working tree.");
        }
        else {
            if (mode.equals("--mixed")) {
                defaultReset(id);
            }
            if (mode.equals("--hard")) {
                hardReset(id);
            }
            if (mode.equals("--soft")) {
                softReset(id);
            }
        }
    }

    /**
     * Check if commit exists. Return whole commitId if exists, else return null.
     * @param commitId
     * @throws IOException
     */
    public static String commitExists(String commitId) throws IOException {
        String lastCommit = new Commit().getLastCommit();
        if (lastCommit == null) {
            return "";
        }
        else {
            do {
                String slicedId = lastCommit.substring(0, 6);
                if (slicedId.equals(commitId)) return lastCommit;
                Commit currentCommit = Commit.deserialize(lastCommit);
                lastCommit = currentCommit.getParent();
            }
            while (!"".equals(lastCommit));
        }
        return "";
    }

    /**
     * Reset in --mixed mode.
     * @param commitId
     * @throws Exception
     */
    public static void defaultReset(String commitId) throws Exception {
        softReset(commitId); // set HEAD

        // delete content of index file
        Index.clearStage();
    }

    /**
     * Reset in --hard mode.
     * @param commitId
     * @throws Exception
     */
    public static void hardReset(String commitId) throws Exception {
        defaultReset(commitId);

        // recover worktree to current commit
        resetWorkDir(commitId);
    }

    /**
     * Recover working directory.
     * @param commitId
     * @throws Exception
     */
    public static void resetWorkDir(String commitId) throws Exception {
        Commit commit = Commit.deserialize(commitId);
        String treeKey = commit.getTree();
        Tree tree = Tree.deserialize(treeKey);
        FileCreation.recoverWorkTree(tree, Repository.getWorkTree());
    }

    /**
     * Reset in --soft mode.
     * @param commitId
     * @throws Exception
     */
    public static void softReset(String commitId) throws Exception {
        File HEAD = new File(Repository.getGitDir() + File.separator + "HEAD");
        String path = GitObject.getValue(HEAD).substring(5).replace("\n", "");
        File branchFile = new File(Repository.getGitDir() + File.separator + path);

        FileWriter fw = new FileWriter(branchFile, false);
        fw.write(commitId);
        fw.close();
    }
}
